package ai.assist.admin.controller.system;

import ai.assist.common.annotation.LogAnnotation;
import ai.assist.common.annotation.LogIgore;
import ai.assist.common.annotation.PassportSSO;
import ai.assist.common.businesss.mongo.entity.*;
import ai.assist.common.dto.admin.*;
import ai.assist.common.businesss.service.UserSessionService;
import ai.assist.common.businesss.mongo.service.SysDeptService;
import ai.assist.common.businesss.mongo.service.SysUserRoleService;
import ai.assist.common.businesss.mongo.service.SysUserService;
import ai.assist.common.businesss.service.UserPermissionService;
import ai.assist.common.context.PassportUserInfoContext;
import ai.assist.common.exception.BusinessException;
import ai.assist.common.utils.CachedBeanCopier;
import ai.assist.common.utils.CheckPasswordMeterUtils;
import ai.assist.common.utils.PasswordUtils;
import ai.assist.common.vo.admin.SysUserInfoVO;
import ai.assist.common.vo.admin.UserRoleOperationReqVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 用户管理
 *
 * @version V1.0
 */
@RestController
@Api(tags = "用户管理", value = "用户管理")
@RequestMapping("/sys/user")
@Slf4j
@PassportSSO
@CrossOrigin(originPatterns = "*", methods = {RequestMethod.GET, RequestMethod.POST})
public class UserController {

    @Autowired
    private UserPermissionService userPermissionService;

    @Autowired
    private SysUserService userService;

    @Autowired
    private UserSessionService userSessionService;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private SysDeptService deptService;

    @PostMapping(value = "/login")
    @ApiOperation(value = "用户登录接口")
    @PassportSSO(ignore = true)
    @LogAnnotation(title = "用户管理", action = "用户登录")
    public Object login(@RequestBody LoginDTO dto, HttpServletRequest httpServletRequest) {
        //校验图像验证码
        validImageCode(dto.getCaptcha());
        return userPermissionService.login(dto, httpServletRequest);
    }

    @PostMapping(value = "/restpwd")
    @PassportSSO(ignore = true)
    @LogAnnotation(title = "用户管理", action = "重置密码")
    public Object restpwd(@RequestBody ResetPwdDTO dto) {
        //校验图像验证码
        validImageCode(dto.getCaptcha());
        SysUser sysUser = userService.limitOne(userService.lambdaQuery().eq(SysUser::getUsername, dto.getUsername()));
        if (null == sysUser) {
            throw new BusinessException("用户名或密码错误");
        }
        if (sysUser.getStatus() == 2) {
            throw new BusinessException("用户名或密码错误");
        }
        if (!PasswordUtils.matches(sysUser.getSalt(), dto.getOldPassword(), sysUser.getPassword())) {
            throw new BusinessException("用户名或密码错误");
        }
        if (!CheckPasswordMeterUtils.CheckPswMeter(dto.getPassword())) {
            throw new BusinessException("密码强度不足!");
        }
        sysUser.setPassword(PasswordUtils.encode(dto.getPassword(), sysUser.getSalt()));
        return userService.updateById(sysUser);
    }

    @PostMapping("/update")
    @ApiOperation(value = "更新用户信息接口")
    @LogAnnotation(title = "用户管理", action = "更新用户信息")
    public Object updateUserInfo(@RequestBody ModifySysUserDTO dto) {
        if (dto.getId() == null) {
            userPermissionService.addUser(dto);
            return true;
        }
        userPermissionService.updateUserInfo(dto);
        return true;
    }

    @PostMapping("/updateSelf")
    @ApiOperation(value = "更新自己信息接口")
    @LogAnnotation(title = "用户管理", action = "更新用户信息")
    public Object updateUserInfoById(@RequestBody ModifyUserMyDTO dto) {
        return userPermissionService.updateUserInfoMy(dto);
    }

    @PostMapping("/{id}")
    @ApiOperation(value = "查询用户详情接口")
    @LogAnnotation(title = "用户管理", action = "查询用户详情")
    public Object detailInfo(@PathVariable("id") Long id) {
        return userService.lambdaQuery().eq(SysUser::getId,id).limitOne();
    }

    @GetMapping("/detail")
    @ApiOperation(value = "查询用户详情接口", response = SysUserInfoVO.class)
    @LogAnnotation(title = "用户管理", action = "查询用户详情")
    @LogIgore
    public Object detail() {
        SysUser userInfo = userService.lambdaQuery().eq(SysUser::getId,PassportUserInfoContext.getContext().getId()).limitOne();
        SysUserInfoVO vo = new SysUserInfoVO();
        CachedBeanCopier.copyObject(userInfo, vo);
        if (userInfo.getDeptId() != null) {
            vo.setDept(deptService.lambdaQuery().eq(SysDept::getId,userInfo.getDeptId()).limitOne());
        }
        List<SysRole> userRoles = userPermissionService.getRoleByUserid(PassportUserInfoContext.getContext().getId());
        vo.setRoles(userRoles);
        List<SysPermission> permissions = userPermissionService.getPermission(PassportUserInfoContext.getContext().getId());
        Set<String> perms = new HashSet<>();
        for (SysPermission sysPermission : permissions) {
            if (sysPermission.getPerms() != null && !StringUtils.isEmpty(sysPermission.getPerms())) {
                Set<String> perm = new HashSet<>(Arrays.asList(sysPermission.getPerms().split(",")));
                perms.addAll(perm);
            }
        }
        vo.setPermissionNodes(userPermissionService.permissionTreeList(PassportUserInfoContext.getContext().getId()));
        vo.setDeptNos(PassportUserInfoContext.getContext().getDeptNos());
        vo.setUnitNo(PassportUserInfoContext.getContext().getUnitNo());
        vo.setParentNo(PassportUserInfoContext.getContext().getParentNo());
        vo.setPerms(perms);
        return vo;
    }

    @PostMapping("/list")
    @ApiOperation(value = "分页获取用户列表接口")
    @LogIgore
    @LogAnnotation(title = "用户管理", action = "分页获取用户列表")
    public Object pageInfo(@RequestBody QueryUserDTO dto) {
        return userPermissionService.pageInfo(dto);
    }

    @PostMapping("/logout")
    @ApiOperation(value = "退出接口")
    @LogAnnotation(title = "用户管理", action = "退出")
    public Object logout() {
        userSessionService.logout(PassportUserInfoContext.getAuthorization());
        return true;
    }

    @PostMapping("/pwd")
    @ApiOperation(value = "修改密码接口")
    @LogAnnotation(title = "用户管理", action = "更新密码")
    public Object updatePwd(@RequestBody ModifySysUserDTO dto) {
        if (StringUtils.isEmpty(dto.getOldPwd()) || StringUtils.isEmpty(dto.getNewPwd())) {
            throw new BusinessException("旧密码与新密码不能为空");
        }
        dto.setId(PassportUserInfoContext.getContext().getId());
        userPermissionService.updatePwd(dto);
        return true;
    }

    @PostMapping("/del")
    @ApiOperation(value = "删除用户接口")
    @LogAnnotation(title = "用户管理", action = "删除用户")
    public Object deletedUser(@RequestBody List<Long> userIds) {
        //删除用户， 删除redis的绑定的角色跟权限
        if (userIds.contains(PassportUserInfoContext.getContext().getId())) {
            throw new BusinessException("不能删除自己");
        }
        userSessionService.abortUserByUserIds(userIds);
        userService.lambdaUpdate().in(SysUser::getId,userIds).remove();
        sysUserRoleService.lambdaUpdate().in(SysUserRole::getUserId, userIds).remove();
        return true;
    }

    @PostMapping("/queryRoles/{userId}")
    @ApiOperation(value = "赋予角色-获取所有角色接口")
    @LogAnnotation(title = "用户管理", action = "赋予角色-获取所有角色接口")
    public Object getUserOwnRole(@PathVariable("userId") Long userId) {
        return userPermissionService.getUserOwnRole(userId);
    }

    @Autowired
    private SysUserRoleService sysUserRoleService;

    @PostMapping("/roles/{userId}/{roleId}")
    @ApiOperation(value = "赋予角色-用户赋予角色接口")
    @LogAnnotation(title = "用户管理", action = "赋予角色-用户赋予角色接口")
    public Object setUserOwnRole(@PathVariable("userId") String userId, @PathVariable String roleId) {
        sysUserRoleService.removeByColumn("user_id", userId);
        if (null != roleId) {
            UserRoleOperationReqVO reqVO = new UserRoleOperationReqVO();
            reqVO.setUserId(userId);
            reqVO.setRoleIds(Arrays.asList(roleId));
            userPermissionService.addUserRoleInfo(reqVO);
        }
        userSessionService.reflashTicket(userId);
        return true;
    }

    /**
     * 校验图像验证码
     *
     * @param imageCode 验证码
     */
    private void validImageCode(String imageCode) {
        String capt = redisTemplate.opsForValue().get("netcom:captcha:" + imageCode);
        if (capt == null || StringUtils.isEmpty(capt) || !capt.equals(imageCode)) {
            throw new BusinessException("验证码输入错误");
        }
        redisTemplate.delete("netcom:captcha:" + imageCode);
    }

}
